use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{RwLock, mpsc};
use tokio::time::{Duration, timeout};
use chrono::Utc;
use tracing::{info, error, warn, debug};

use crate::config::{ConfigManager, WriteConfig};
use crate::modbus::{ModbusClientManager, DataParser};
use crate::storage::DataStorage;
use crate::api::models::{WriteRequest, WriteResponse};
use crate::error::{Result, ModbusCollectorError};

/// 写指令处理器
#[derive(Debug)]
pub struct WriteHandler {
    config_manager: ConfigManager,
    modbus_manager: ModbusClientManager,
    storage: DataStorage,
    pending_writes: Arc<RwLock<HashMap<String, PendingWrite>>>,
    write_queue_tx: mpsc::UnboundedSender<WriteCommand>,
    write_queue_rx: Option<mpsc::UnboundedReceiver<WriteCommand>>,
}

/// 待处理的写入操作
#[derive(Debug)]
struct PendingWrite {
    command: WriteCommand,
    timestamp: chrono::DateTime<chrono::Utc>,
    retries: u32,
}

/// 写入命令
#[derive(Debug)]
pub struct WriteCommand {
    pub request_id: String,
    pub point_id: String,
    pub value: f64,
    pub auth_token: Option<String>,
    pub response_tx: tokio::sync::oneshot::Sender<WriteResponse>,
}

/// 写入执行数据（不包含响应通道）
#[derive(Debug, Clone)]
struct WriteExecutionData {
    pub point_id: String,
    pub value: f64,
    pub auth_token: Option<String>,
}

/// 写入结果
#[derive(Debug, Clone)]
pub struct WriteResult {
    pub point_id: String,
    pub success: bool,
    pub message: String,
    pub execution_time_ms: u64,
}

impl WriteHandler {
    pub fn new(
        config_manager: ConfigManager,
        modbus_manager: ModbusClientManager,
        storage: DataStorage,
    ) -> Self {
        let (write_queue_tx, write_queue_rx) = mpsc::unbounded_channel();
        
        Self {
            config_manager,
            modbus_manager,
            storage,
            pending_writes: Arc::new(RwLock::new(HashMap::new())),
            write_queue_tx,
            write_queue_rx: Some(write_queue_rx),
        }
    }
    
    /// 启动写指令处理器
    pub async fn start(&mut self) -> Result<()> {
        info!("Starting write handler");
        
        let mut write_queue_rx = self.write_queue_rx.take()
            .ok_or_else(|| ModbusCollectorError::Other(anyhow::anyhow!("Write handler already started")))?;
        
        let config_manager = self.config_manager.clone();
        let modbus_manager = self.modbus_manager.clone();
        let storage = self.storage.clone();
        
        // 启动写入处理循环
        tokio::spawn(async move {
            while let Some(command) = write_queue_rx.recv().await {
                let point_id = command.point_id.clone();
                let value = command.value;
                let auth_token = command.auth_token.clone();
                let response_tx = command.response_tx;
                
                // 创建一个简化的命令结构体传递给执行函数
                let exec_command = WriteExecutionData {
                    point_id: point_id.clone(),
                    value,
                    auth_token,
                };
                
                let result = Self::execute_write_operation(
                    &config_manager,
                    &modbus_manager,
                    &storage,
                    exec_command
                ).await;
                
                let response = match result {
                    Ok(write_result) => WriteResponse {
                        point_id: write_result.point_id,
                        success: write_result.success,
                        message: write_result.message,
                        timestamp: Utc::now(),
                    },
                    Err(e) => WriteResponse {
                        point_id: point_id.clone(),
                        success: false,
                        message: format!("Write operation failed: {}", e),
                        timestamp: Utc::now(),
                    },
                };
                
                // 发送响应
                if let Err(_) = response_tx.send(response) {
                    warn!("Failed to send write response for point {}", point_id);
                }
            }
        });
        
        info!("Write handler started successfully");
        Ok(())
    }
    
    /// 提交写入请求
    pub async fn submit_write_request(&self, request: WriteRequest) -> Result<WriteResponse> {
        debug!("Submitting write request for point: {}", request.point_id);
        
        // 验证权限和配置
        self.validate_write_request(&request).await?;
        
        let (response_tx, response_rx) = tokio::sync::oneshot::channel();
        let request_id = uuid::Uuid::new_v4().to_string();
        
        let command = WriteCommand {
            request_id,
            point_id: request.point_id,
            value: request.value,
            auth_token: request.auth_token,
            response_tx,
        };
        
        // 发送到处理队列
        self.write_queue_tx.send(command)
            .map_err(|_| ModbusCollectorError::Other(anyhow::anyhow!("Write queue is closed")))?;
        
        // 等待响应（带超时）
        match timeout(Duration::from_secs(10), response_rx).await {
            Ok(Ok(response)) => Ok(response),
            Ok(Err(_)) => Err(ModbusCollectorError::Other(anyhow::anyhow!("Response channel closed"))),
            Err(_) => Err(ModbusCollectorError::Other(anyhow::anyhow!("Write operation timeout"))),
        }
    }
    
    /// 验证写入请求
    async fn validate_write_request(&self, request: &WriteRequest) -> Result<()> {
        // 检查点位是否存在
        let point_config = self.config_manager.get_point(&request.point_id).await
            .ok_or_else(|| ModbusCollectorError::Config(
                format!("Point not found: {}", request.point_id)
            ))?;
        
        // 检查写入配置
        let write_config = self.config_manager.get_write_config(&request.point_id).await
            .ok_or_else(|| ModbusCollectorError::Config(
                format!("Point {} is not writable", request.point_id)
            ))?;
        
        // 检查值范围
        if request.value < write_config.min_value || request.value > write_config.max_value {
            return Err(ModbusCollectorError::Config(
                format!("Value {} is out of range [{}, {}] for point {}",
                        request.value, write_config.min_value, write_config.max_value, request.point_id)
            ));
        }
        
        // 检查访问权限（简化实现）
        if write_config.access_level == "admin" && request.auth_token.is_none() {
            return Err(ModbusCollectorError::Config(
                "Admin access required for this write operation".to_string()
            ));
        }
        
        Ok(())
    }
    
    /// 执行写入操作
    async fn execute_write_operation(
        config_manager: &ConfigManager,
        modbus_manager: &ModbusClientManager,
        _storage: &DataStorage,
        command: WriteExecutionData,
    ) -> Result<WriteResult> {
        let start_time = std::time::Instant::now();
        
        debug!("Executing write command for point: {}", command.point_id);
        
        // 获取点位配置
        let point_config = config_manager.get_point(&command.point_id).await
            .ok_or_else(|| ModbusCollectorError::Config(
                format!("Point not found: {}", command.point_id)
            ))?;
        
        // 获取设备配置
        let device_config = config_manager.get_device(&point_config.device_id).await
            .ok_or_else(|| ModbusCollectorError::Config(
                format!("Device not found: {}", point_config.device_id)
            ))?;
        
        // 获取写入配置
        let write_config = config_manager.get_write_config(&command.point_id).await
            .ok_or_else(|| ModbusCollectorError::Config(
                format!("Write config not found for point: {}", command.point_id)
            ))?;
        
        // 将工程值转换为原始值
        let raw_values = DataParser::encode_data(command.value, &point_config)?;
        
        let result = match Self::get_address_type(point_config.address) {
            Some(address_type) => {
                Self::execute_modbus_write(
                    modbus_manager,
                    &device_config,
                    &point_config,
                    &write_config,
                    &raw_values,
                    address_type,
                ).await
            },
            None => {
                Err(ModbusCollectorError::Config(
                    format!("Invalid Modbus address: {}", point_config.address)
                ))
            }
        };
        
        let execution_time = start_time.elapsed().as_millis() as u64;
        
        match result {
            Ok(_) => {
                info!("Successfully wrote value {} to point {} in {}ms", 
                      command.value, command.point_id, execution_time);
                
                Ok(WriteResult {
                    point_id: command.point_id,
                    success: true,
                    message: format!("Write operation completed successfully in {}ms", execution_time),
                    execution_time_ms: execution_time,
                })
            },
            Err(e) => {
                error!("Failed to write value {} to point {}: {}", 
                       command.value, command.point_id, e);
                
                Ok(WriteResult {
                    point_id: command.point_id,
                    success: false,
                    message: format!("Write operation failed: {}", e),
                    execution_time_ms: execution_time,
                })
            }
        }
    }
    
    /// 执行Modbus写入操作
    async fn execute_modbus_write(
        modbus_manager: &ModbusClientManager,
        device_config: &crate::config::DeviceConfig,
        point_config: &crate::config::PointConfig,
        write_config: &WriteConfig,
        raw_values: &[u16],
        address_type: AddressType,
    ) -> Result<()> {
        let zero_based_address = Self::to_zero_based_address(point_config.address)?;
        
        match (address_type, write_config.write_function) {
            (AddressType::Coil, 5) => {
                // 写单个线圈
                let value = raw_values[0] != 0;
                modbus_manager.write_single_coil(device_config, zero_based_address, value).await
            },
            (AddressType::Coil, 15) => {
                // 写多个线圈
                let values: Vec<bool> = raw_values.iter().map(|&v| v != 0).collect();
                modbus_manager.write_multiple_coils(device_config, zero_based_address, &values).await
            },
            (AddressType::HoldingRegister, 6) => {
                // 写单个寄存器
                modbus_manager.write_single_register(device_config, zero_based_address, raw_values[0]).await
            },
            (AddressType::HoldingRegister, 16) => {
                // 写多个寄存器
                modbus_manager.write_multiple_registers(device_config, zero_based_address, raw_values).await
            },
            _ => {
                Err(ModbusCollectorError::Config(
                    format!("Unsupported write operation: function {} on address type {:?}",
                            write_config.write_function, address_type)
                ))
            }
        }
    }
    
    /// 获取地址类型
    fn get_address_type(address: u32) -> Option<AddressType> {
        match address {
            1..=65536 => Some(AddressType::Coil),
            100001..=165536 => Some(AddressType::DiscreteInput),
            300001..=365536 => Some(AddressType::InputRegister),
            400001..=465536 => Some(AddressType::HoldingRegister),
            _ => None,
        }
    }
    
    /// 转换为0基址
    fn to_zero_based_address(address: u32) -> Result<u16> {
        match address {
            1..=65536 => Ok((address - 1) as u16),
            100001..=165536 => Ok((address - 100001) as u16),
            300001..=365536 => Ok((address - 300001) as u16),
            400001..=465536 => Ok((address - 400001) as u16),
            _ => Err(ModbusCollectorError::Config(
                format!("Invalid Modbus address: {}", address)
            )),
        }
    }
    
    /// 获取写处理器统计信息
    pub async fn get_statistics(&self) -> WriteHandlerStats {
        let pending_count = self.pending_writes.read().await.len();
        
        WriteHandlerStats {
            pending_writes: pending_count,
            total_writes_processed: 0, // 可以添加计数器
            successful_writes: 0,      // 可以添加计数器
            failed_writes: 0,          // 可以添加计数器
        }
    }
}

/// 地址类型
#[derive(Debug, Clone, Copy)]
enum AddressType {
    Coil,
    DiscreteInput,
    InputRegister,
    HoldingRegister,
}

/// 写处理器统计信息
#[derive(Debug, serde::Serialize)]
pub struct WriteHandlerStats {
    pub pending_writes: usize,
    pub total_writes_processed: u64,
    pub successful_writes: u64,
    pub failed_writes: u64,
}